print("加载AliYun_Task.lua！")
module(..., package.seeall)
require "aLiYun"
require "sys"
require "fn"
require "net"
require "ntp"

print("采取一型一密")

local function getDeviceName()
    print("getDeviceName()", _G.MOD_IMEI)
    return _G.MOD_IMEI
end
local function getDeviceSecret()
    return misc.getSn()
end

local function setDeviceSecret(s)
    misc.setSn(s)
end

--把收到的消息发给MCU
local function cmd_0x12(payload)
    print("把收到的消息发给单片机！！")
    fn.uart_answer(0x12, payload)
end
local function cmd_0x14(payload, msg_id)
    print("收到RRPC指令！")
    fn.uart_answer_rrpc(0x14, payload, msg_id)
end
--大文件传输处理
local function big_send_task(payload)
    print("开始大文件传输任务！", payload)
    local tmpstr = payload
    local count = 1
    _G.BIG_FILE_COUNT = 0
    while #tmpstr > 0 do
        process_str = string.sub(tmpstr, 1, _G.BIG_FILE_BUFFER_SIZE)
        print(process_str)
        fn.uart_answer_bigfile(0x13, #payload, count, process_str)
        tmpstr = string.sub(tmpstr, _G.BIG_FILE_BUFFER_SIZE + 1, -1)
        local wait_time = 0
        while _G.BIG_FILE_COUNT < count and wait_time < _G.BIG_FILE_ANS_TIMEOUT do
            print("等待下端回复中...！")
            print("_G.BIG_FILE_COUNT=", _G.BIG_FILE_COUNT, "！")
            sys.wait(_G.BIG_FILE_ANS_CHECK_TIME)
            wait_time = wait_time + _G.BIG_FILE_ANS_CHECK_TIME
        end
        if _G.BIG_FILE_COUNT < count or wait_time >= _G.BIG_FILE_ANS_TIMEOUT then
            print("回复超时...！")
            return false
        end

        count = count + 1
    end
end

local function publishOK_rrpc(...)
    print("******publishOK_rrpc()")
    _G.SYS_BUSY = 0
    fn.print_table(arg)
end

local function cmd_0x15(payload, msg_id)
    print("开始RRPC指令的应答！")
    print("d_payload", string.toHex(payload), "！")
    print("msg_id", msg_id, "！") 
    --msg_id = _G.TEST_MSG_ID   -- 由于用鼠标在串口复制这个ID的手速不够快，所以临时用这个测试

    print("log  id",string.toHex(_G.TEST_MSG_ID))
    print("uart id",string.toHex(msg_id))
    local topic = "/sys/" .. _G.PRODUCT_KEY .. "/" .. _G.MOD_IMEI .. "/rrpc/response/" .. msg_id
    print("******topic=", topic)
   
    
    aLiYun.publish(topic, payload, 0, publishOK_rrpc, 0x15)
    --模拟返回hello
end

--阿里云收到主题消息的回调
local function rcvCbFnc(topic, qos, payload)
    print("订阅主题收到了消息", topic, qos, "！")
    local topic_end = fn.Split(topic, "/")

    fn.print_table(topic_end)
    if topic_end[2] == "sys" and topic_end[5] == "rrpc" and topic_end[6] == "request" then
        cmd_0x14(payload, topic_end[7])
        _G.TEST_MSG_ID = topic_end[7]
        -- 由于用鼠标在串口复制这个ID的手速不够快，所以临时用这个测试
        --cmd_0x15(payload, topic_end[7])
        return
    end

    if topic_end[4] ~= nil and topic_end[4] == "update_qrcode" then
        print("send qrcode")
        sys.taskInit(big_send_task, payload)
        return
    end

    local bindata = string.fromHex(payload)
    print("还原", string.toHex(bindata), "！")
    if not payload or payload == "" then
        return
    end
    if #payload > 255 then
        sys.taskInit(big_send_task, payload)
        return
    end
    if #payload < 256 then
        cmd_0x12(payload)
    end
end

local function connectCbFnc(result)
    log.info("阿里云连接结果", result, "！")
    sConnected = result
    if result then
        _G.MOD_NET_STAT = _G.STAT_ALI_CONN_OK

        aLiYun.subscribe(
            {
                ["/" .. _G.PRODUCT_KEY .. "/" .. _G.MOD_IMEI .. "/get"] = 0,
                ["/" .. _G.PRODUCT_KEY .. "/" .. _G.MOD_IMEI .. "/get"] = 1,
                ["/" .. _G.PRODUCT_KEY .. "/" .. _G.MOD_IMEI .. "/update_qrcode"] = 0,
                ["/sys/" .. _G.PRODUCT_KEY .. "/" .. _G.MOD_IMEI .. "/rrpc/request/+"] = 0
            }
        )
        aLiYun.on("receive", rcvCbFnc)
        print("注册数据接收的处理函数！")
    end
end

local function authCbFnc(result)
    _G.MOD_NET_STAT = _G.STAT_ALI_AUTH_OK
    log.info("阿里云的认证结果", result, "！")
    sys.publish("NTP_SYNC")
end

local function cmd_0x00()
    print("收到MCU发送的心跳指令！")
    fn.uart_answer(0)
end
local function cmd_0x01()
    print("收到MCU发送的状态查询指令！")
    print("当前模块状态", _G.MOD_NET_STAT)
    fn.uart_answer(0x01, string.char(_G.MOD_NET_STAT))
end
local function cmd_0x02()
    print("收到MCU发送的IMEI查询指令！")
    print("当前模块IMEI", _G.MOD_IMEI, "！")
    fn.uart_answer(0x02, _G.MOD_IMEI)
end
local function cmd_0x03()
    print("收到MCU发送的查询信号强度！")
    fn.uart_answer(0x03, string.char(net.getRssi()))
end

local function publishOK(...)
    print("publishOK()")
    fn.print_table(arg)
    fn.uart_answer(0x11, string.char(0x00))
end

local function cmd_0x11(...)
    print("收到MCU发送的数据上传指令！")
    fn.print_table(arg)
    print("d_payload", string.toHex(arg[1]), "！")
    if _G.MOD_NET_STAT < _G.STAT_ALI_CONN_OK then
        print("ERROR：模块还没有正确连接阿里云！！")
        fn.uart_answer(0x11, string.char(0x01))
        return
    end

    aLiYun.publish(
        "/" .. _G.PRODUCT_KEY .. "/" .. getDeviceName() .. "/update",
        string.toHex(arg[1]),
        0,
        publishOK,
        0x11
    )
end

local function cmd_0x13(...)
    print("收到MCU发送的大文件应答！")
    print("d_payload", string.toHex(arg[1]), "！")
    _G.BIG_FILE_COUNT = string.byte(arg[1])
end





local function ntp_to_mcu(...)
    fn.print_table(arg)
    if arg[2] == true then
        local timestr =
            string.format(
            "%04d/%02d/%02d,%02d:%02d:%02d",
            arg[1].year,
            arg[1].month,
            arg[1].day,
            arg[1].hour,
            arg[1].min,
            arg[1].sec
        )
        print("发送时间给mcu！", timestr, "！")
        fn.uart_answer(0x04, timestr)
    end
end

local function ntp_sync()
    print("同步NTP！")
    ntp.timeSync(1, ntp_to_mcu)
end

sys.subscribe("MQ_CMD_0x00", cmd_0x00)
sys.subscribe("MQ_CMD_0x01", cmd_0x01)
sys.subscribe("MQ_CMD_0x02", cmd_0x02)
sys.subscribe("MQ_CMD_0x03", cmd_0x03)
sys.subscribe("MQ_CMD_0x11", cmd_0x11)
sys.subscribe("MQ_CMD_0x13", cmd_0x13)
sys.subscribe("MQ_CMD_0x15", cmd_0x15)

sys.subscribe("NTP_SYNC", ntp_sync)


aLiYun.on("auth", authCbFnc)
aLiYun.on("connect", connectCbFnc)
aLiYun.setMqtt(1,{qos=0,retain=1,topic="/willTopic",payload="will payload"},60) --1分钟不心跳离线 
aLiYun.setup(_G.PRODUCT_KEY, _G.PRODUCE_SECRET, getDeviceName, getDeviceSecret, setDeviceSecret)

